#ifndef mbObj

#include "sys_ext.h" 
#include "os_obj.h"
#include "mbapp.h"
#include "com_def.h"

#define mb_port                       UART4
#define mbURT_IRQn                   UART4_IRQn
#define mb_isr                        MB_UART4_IRQHandler
#define RCU_USARTRST                 UART4_RST
#define mbObj                        mb.obj04

#define MB_RX_FIFO_LEN				 14
#define MB_TX_FIFO_LEN				 14
#define mb_rx_dir_enable()	
#define mb_tx_dir_enable()	
static void mb_cb_set(void)
{
}
static void mb_port_hal_cfg(void)
{
}

#endif


static void mb_timer_handler(void);
static void mb_cb_set(void);
static void mb_hal_obj_init(mb_mode_type mb_mode);
static void mb_hal_rx0_tx1(uint8_t mode);
static void mb_port_init(mb_mode_type mb_mode, uint32_t ulBaudRate, mb_parity_type eParity);
static void mb_hal_dat_send(void);
static void mb_port_hal_cfg(void);
static void(*mb_byte_send)(uint8_t dat);

/*****************************************************************************
* @brief mb_byte_send
* @param   dat
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/

static void mb_rtu_byte_send(uint8_t dat)
{
	mb_port->DAT = dat;
}

static void mb_asc_byte_send(uint8_t dat)
{
	mb_port->DAT = dat;
}

/*****************************************************************************
* @brief   Uart interrupt.
* @param   none
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/
void mb_isr()
{
	volatile uint32_t int_st;
	volatile uint8_t dat;

	mbObj.timeout_cnt = 0;

	int_st = mb_port->INTSTS;

	//RX超时中断
	if (int_st & UART_INTSTS_RXTOINT_Msk)
	{
		// 读数据
		if(mb_data_pre_rcv(&mbObj))
		{
			while (!(mb_port->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk))
			{
				mb_data_rcv_directly(&mbObj, mb_port->DAT);
			}
		}
		else
		{
			while (!(mb_port->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk))
			{
				dat = mb_port->DAT;
			}
		}

		// 接收结束
		if (mbObj.rcv_st == MB_RX_RCV)
		{
			if (mb_port->FIFOSTS & (UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_RXOVIF_Msk))
			{
				if (mbObj.rcv_cnt >= 2)
				{
					//错误标记写1清零，写零位忽略
					mb_port->FIFOSTS = UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_RXOVIF_Msk;
					mbObj.err_st.bits.hal = 1;
				}
			}

			// rtu 模式超时中断作为结束
			if (mbObj.run_st.bits.rtu_mode)
			{
				mbObj.rcv_st = MB_RX_RCVEND;
			}
		}
	}

	//接收缓冲触发中断
	else if (int_st & UART_INTSTS_RDAINT_Msk)
	{
		uint8_t fifo_len;

		//读取时留一字节用于产生超时中断
		fifo_len = MB_RX_FIFO_LEN - 1;

		mb_data_rcv_u32_fifo(&mbObj, &mb_port->DAT, fifo_len);
		
		if (mbObj.rcv_st == MB_RX_RCV)
		{
			if (mb_port->FIFOSTS & (UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_RXOVIF_Msk))
			{
				if (mbObj.rcv_cnt >= 2)
				{
					//错误标记写1清零，写零位忽略
					mb_port->FIFOSTS = UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_RXOVIF_Msk;
					mbObj.err_st.bits.hal = 1;
				}
			}

			mbObj.run_st.bits.port_st = 1;
		}
	}

	// 发送缓冲空触发
	if (int_st & UART_INTSTS_THREINT_Msk)
	{
		if (mb_data_send_u32_fifo(&mbObj, &mb_port->DAT, MB_TX_FIFO_LEN))
		{
			mb_port->INTEN = UART_INTEN_TXENDIEN_Msk;
		}
	}
	// 发送结束中断
	else if (int_st & UART_INTSTS_TXENDINT_Msk)
	{
		mb_send_end(&mbObj);
		mb_hal_rx0_tx1(0);
	}
	else
	{

	}

	__DSB();
}

/*****************************************************************************
* @brief   com modle init .
* @param   mb_mode-ulBaudRate-eParity
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/
static void mb_port_init(mb_mode_type mb_mode, uint32_t ulBaudRate, mb_parity_type eParity)
{
	uint32_t us10TimerSv;
	uint32_t stop_bits, parity_set, len_set;

	nvic_irq_set(mbURT_IRQn, 0x0F, 0);
	
	intx_disable();
	SYS_ResetModule(RCU_USARTRST);
	intx_enable();

	mb_port_hal_cfg();

	mb_hal_obj_init(mb_mode);

	mb_byte_send = mb_rtu_byte_send;
	len_set = UART_WORD_LEN_8;

	if (mb_mode == MB_RTU_MASTER || mb_mode == MB_RTU_SLAVE)
	{
		// rtu mode
		if (MB_PAR_NONE == eParity)
		{
			parity_set = UART_PARITY_NONE;
			stop_bits = UART_STOP_BIT_2;
		}
		else if (MB_PAR_NONE_1S == eParity)
		{
			parity_set = UART_PARITY_NONE;
			stop_bits = UART_STOP_BIT_1;
		}
		else if (MB_PAR_ODD == eParity)
		{
			parity_set = UART_PARITY_ODD;
			stop_bits = UART_STOP_BIT_1;
		}
		else
		{
			parity_set = UART_PARITY_EVEN;
			stop_bits = UART_STOP_BIT_1;
		}

		mbObj.run_st.bits.rtu_mode = 1;
	}
	else
	{
		// asc mode
		if (MB_PAR_NONE == eParity)
		{
			parity_set = UART_PARITY_NONE;
			stop_bits = UART_STOP_BIT_2;
		}
		else if (MB_PAR_NONE_1S == eParity)
		{
			parity_set = UART_PARITY_NONE;
			stop_bits = UART_STOP_BIT_1;
		}
		else if (MB_PAR_ODD == eParity)
		{
			parity_set = UART_PARITY_ODD;
			stop_bits = UART_STOP_BIT_1;
		}
		else
		{
			parity_set = UART_PARITY_EVEN;
			stop_bits = UART_STOP_BIT_1;
		}

		len_set = UART_WORD_LEN_7;
		mb_byte_send = mb_asc_byte_send;
		mbObj.run_st.bits.rtu_mode = 0;
	}

	UART_Open(mb_port, ulBaudRate);
	UART_SetLineConfig(mb_port, ulBaudRate, len_set, parity_set, stop_bits);

	//接收FIFO触发深度
	mb_port->FIFO &= ~UART_FIFO_RFITL_Msk;
	mb_port->FIFO |= UART_FIFO_RFITL_14BYTES;

	//超时时间计算
	if (ulBaudRate >= 19200)
	{
		uint32_t clk_num;

		clk_num = 2000 * ulBaudRate / 1000000;

		if (clk_num < 41)
			clk_num = 41;

		mb_port->TOUT = (1UL << 8) | (clk_num);
	}
	else
	{
		mb_port->TOUT = (1UL << 8) | (41);
	}

	// 软件超时
	if (mbObj.run_st.bits.rtu_mode)
	{
		if (ulBaudRate > 19200)
		{
			us10TimerSv = com_timer_cal(ulBaudRate, 12 * (5 + 16), 300, 20000);

			mbObj.rtu_timer_sv = 4 + us10TimerSv / 100;
		}
		else
		{
			us10TimerSv = com_timer_cal(ulBaudRate, 12 * (5 + 16), 300, 20000);

			mbObj.rtu_timer_sv = 10 + us10TimerSv / 100;
		}
	}
	else
	{
		mbObj.rtu_timer_sv = 100;
	}

	// 开中断
	nvic_irq_set(mbURT_IRQn, 0x0F, 1);

	mb_hal_rx0_tx1(0);
}

/*****************************************************************************
* @brief   Uart En or Dis.
* @param   mode : r/w
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/

static void mb_hal_rx0_tx1(uint8_t mode)
{
	volatile uint8_t u8Temp;

	if (0 == mode)
	{
		// 接收
		volatile uint8_t u8Temp;

		mb_rx_dir_enable();

		mb_port->INTEN = 0;

		while (!(mb_port->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk))
		{
			u8Temp = mb_port->DAT;
		}

		mb_port->FIFO &= ~UART_FIFO_RXOFF_Msk;

		mb_port->INTEN = UART_INTEN_RDAIEN_Msk | UART_INTEN_TOCNTEN_Msk | UART_INTEN_RXTOIEN_Msk;
	}
	else
	{
		// 发送
		mb_port->INTEN = 0;

		mb_port->FIFO |= UART_FIFO_RXOFF_Msk;

		mb_tx_dir_enable();

		// 如果小于缓冲长度，直接结束中断，减少中断次数
		if (mb_data_send_u32_fifo(&mbObj, &mb_port->DAT, MB_TX_FIFO_LEN))
		{
			mb_port->INTEN = UART_INTEN_TXENDIEN_Msk;
		}
		else
		{
			mb_port->INTEN = UART_INTEN_THREIEN_Msk;
		}
	}
}

/*****************************************************************************//*!
* @brief   Send data.
* @param   none
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/
static void mb_hal_dat_send(void)
{
	mb_hal_rx0_tx1(1);
}


/*****************************************************************************//*!
* @brief   Timeout handle.
* @param   none
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/
void mb_timer_handler(void)
{
	mb_rtu_timer_run(&mbObj);
}

/*****************************************************************************//*!
* @brief   mb object init.
* @param   none
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/
static void mb_hal_obj_init(mb_mode_type mb_mode)
{

	mb_obj_init(&mbObj);

	mbObj.adu_send = &mb_hal_dat_send;

	mb_cb_set();

	mbObj.master.err_cnt = 0;

	//SLAVE FUNCTION INIT
	if (MB_RTU_MASTER == mb_mode || mb_mode == ASCII_MASTER)
	{
		mbObj.run_st.bits.master_mode = 1;
	}
	else
	{
		mbObj.run_st.bits.master_mode = 0;
	}
}
